package com.learn.sqlsession.impl;

import com.learn.pojo.Configuration;
import com.learn.pojo.MappedStatement;
import com.learn.sqlsession.Executor;
import com.learn.sqlsession.SqlSession;

import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DefaultSqlsession implements SqlSession {
    private Configuration configuration;
    private Executor executor;

    public DefaultSqlsession(Configuration configuration) {
        this.configuration = configuration;
        this.executor = new SimpleExecutor();
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... params) throws Exception {
        MappedStatement statement = configuration.getMappedStatementMap().get(statementId);
        //TODO:编写Executor query() 用于执行查询
        List<E> query = executor.query(configuration, statement, params);
        return query;
    }

    @Override
    public <T> T selectOne(String statementId, Object... params) throws Exception {
        List<T> list = selectList(statementId, params);
        if (list.size() == 1) {
            return list.get(0);
        } else {
            throw new RuntimeException("返回结果过多");
        }
    }

    @Override
    public void close() throws SQLException {
        executor.close();
    }

    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        return (T) Proxy.newProxyInstance(mapperClass.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //selectOne
                String methodName = method.getName();
                //className:namespace
                //com.demo.dao.IUserDao
                String className = method.getDeclaringClass().getName();
                String key = className + "." + methodName;
                MappedStatement statement = configuration.getMappedStatementMap().get(key);
                Type genericReturnType = method.getGenericReturnType();
                ArrayList arrayList = new ArrayList();
                //判断是否实现泛型类型参数化
                if (genericReturnType instanceof ParameterizedType) {
                    return selectList(key, args);
                }
                return selectOne(key, args);
            }
        });
    }
}
